Transcrição
O template de photo-list.component.html possui a primeira <div> correspondendo ao topo da página com o campo de busca, e na página temos <ap-load-button>, <ap-photos>, e a parte de search (busca), certo?
Com o Angular, a ideia é que tenhamos o mínimo possível de HTML para trabalhar. Sendo assim, esta primeira <div> é um forte candidato a se tornar um componente. É o que faremos — componentizaremos o máximo que pudermos para melhorar a legibilidade e manutenção do nosso código.
Já que esta área de busca será exclusiva a "photo-list", criaremos nela uma pasta denominada "search", com o componente search.component.ts e o template search.component.html. O primeiro terá o seguinte conteúdo:
@Component({
selector: 'ap-search',
templateUrl: './search.component.html'
})
export class SearchComponent { }Recortaremos de photo-list.component.html a <div> referente à caixa de busca, e a colaremos em search.component.html, salvando-o em seguida:
<div class="">
<form>
<i aria-hidden="true" class="fa fa-search mr-1"></i>
<input
class="rounded"
type="search"
placeholder="search..."
autofocus
(keyup)="debounce.next($event.target.value)"
>
</form>
</div>Em photo-list.component.ts há o debounce para lidar com a questão da digitação do input, não mais necessário, portanto moveremos a linha debounce: Subject<string> = new Subject<string>(); e deletaremos import { Subject } from 'rxjs';, e deixaremos SearchComponent de search.component.ts do seguinte modo:
export class SearchComponent {
debounce: Subject<string> = new Subject<string>();
}Em seguida, removeremos o trecho a seguir de ngOnInit() do photo-list.component.ts:
this.debounce
.pipe(debounceTime(300))
.subscribe(filter => this.filter = filter);E faremos o mesmo com
ngOnDestroy(): void {
this.debounce.unsubscribe();
}Com isso, simplificamos o componente. Poderemos deletar também os importes de debounceTime e OnDestroy, e a exportação deste. E precisaremos adicionar o debounce no ngOnInit() de search.component.ts, não esquecendo de importá-lo. Incluiremos implements OnInit na clase SearchComponent, e removeremos as demais linhas de ngOnInit().
Então, implementaremos OnDestroy, e em ngOnDestroy() incluiremos o unsubscribe de debounce. O arquivo ficará assim:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Component({
selector: 'ap-search',
templateUrl: './search.component.html'
})
export class SearchComponent implements OnInit, OnDestroy {
debounce: Subject<string> = new Subject<string>();
ngOnInit(): void {
this.debounce
.pipe(debounceTime(300));
}
ngOnDestroy(): void {
this.debounce.unsubscribe();
}
}Salvaremos, abriremos photo-list.component.html e incluiremos, no topo do código, de modo a termos três componentes:
<ap-search></ap-search>Salvaremos tudo, abriremos o navegador e obteremos um erro que aponta que faltou acrescentarmos SearchComponent no NgModule de photo-list.module.ts. Além disso, ao testarmos o campo de pesquisa, notaremos que o filtro não funciona. Temos um componente isolado que precisa se comunicar com outro. Isto é, para interagirmos com o <ap-search> de photo-list.component.html, ele precisa se comunicar com photo-list.component.ts, pois ele precisa atualizar a propriedade filter para que o filtro de fato funcione.
Como faremos essa comunicação entre componentes hierarquicamente organizados?